//+------------------------------------------------------------------+
//| 日志系统头文件 - Logger.mqh                                        |
//| 提供完整的日志记录功能，支持文件日志和控制台日志                   |
//+------------------------------------------------------------------+

// 日志控制宏定义
#define SUPPRESS_SYSTEM_LOGS
#ifdef SUPPRESS_SYSTEM_LOGS
    #define SYSTEM_LOG_LEVEL LOG_LEVEL_NO
#else
    #define SYSTEM_LOG_LEVEL LOG_LEVEL_ALL
#endif

// 日志前缀定义
#define LOG_PREFIX "[MartingaleEA]"
#define LOG_INFO LOG_PREFIX + " [INFO] "
#define LOG_WARN LOG_PREFIX + " [WARN] "
#define LOG_ERROR LOG_PREFIX + " [ERROR] "
#define LOG_DEBUG LOG_PREFIX + " [DEBUG] "

// 日志级别枚举
enum ENUM_LOG_LEVEL {
    LOG_LEVEL_NONE = 0,    // 不输出日志
    LOG_LEVEL_ERROR = 1,   // 只输出错误
    LOG_LEVEL_WARN = 2,    // 输出警告和错误
    LOG_LEVEL_INFO = 3,    // 输出信息、警告和错误
    LOG_LEVEL_DEBUG = 4    // 输出所有日志
};

//+------------------------------------------------------------------+
//| 日志系统类                                                        |
//+------------------------------------------------------------------+
class CLogger {
private:
    int m_fileHandle;
    string m_fileName;
    ENUM_LOG_LEVEL m_logLevel;
    bool m_isInitialized;
    
public:
    CLogger() {
        m_fileHandle = INVALID_HANDLE;
        m_isInitialized = false;
        m_logLevel = LOG_LEVEL_INFO;
    }
    
    ~CLogger() {
        Close();
    }
    
    bool Initialize(string fileName = "", ENUM_LOG_LEVEL logLevel = LOG_LEVEL_INFO) {
        if(m_isInitialized) return true;
        
        m_logLevel = logLevel;
        
        // 生成文件名
        if(fileName == "") {
            datetime currentTime = TimeCurrent();
            string timeStr = TimeToString(currentTime, TIME_DATE|TIME_MINUTES);
            timeStr = StringReplace(timeStr, ".", "");
            timeStr = StringReplace(timeStr, ":", "");
            fileName = "MartingaleEA_" + timeStr + ".log";
        }
        
        m_fileName = fileName;
        
        // 创建日志目录
        string logDir = "Logs";
        if(!FolderCreate(logDir)) {
            int error = GetLastError();
            if(error != 5130) { // ERR_DIRECTORY_EXISTS = 5130
                Print("创建日志目录失败: ", error);
                return false;
            }
        }
        
        // 打开日志文件
        string fullPath = logDir + "\\" + m_fileName;
        m_fileHandle = FileOpen(fullPath, FILE_WRITE|FILE_TXT|FILE_ANSI);
        
        if(m_fileHandle == INVALID_HANDLE) {
            Print("打开日志文件失败: ", GetLastError());
            return false;
        }
        
        m_isInitialized = true;
        
        // 写入日志头
        string header = "=== Martingale EA 日志文件 ===\n";
        header += "开始时间: " + TimeToString(TimeCurrent()) + "\n";
        header += "日志级别: " + EnumToString(m_logLevel) + "\n";
        header += "================================\n\n";
        
        FileWriteString(m_fileHandle, header);
        FileFlush(m_fileHandle);
        
        return true;
    }
    
    void Close() {
        if(m_fileHandle != INVALID_HANDLE) {
            FileClose(m_fileHandle);
            m_fileHandle = INVALID_HANDLE;
        }
        m_isInitialized = false;
    }
    
    void Log(ENUM_LOG_LEVEL level, string message, bool enableConsoleLog = false) {
        if(!m_isInitialized || level > m_logLevel) return;
        
        string levelStr = "";
        switch(level) {
            case LOG_LEVEL_ERROR: levelStr = "[ERROR]"; break;
            case LOG_LEVEL_WARN:  levelStr = "[WARN] "; break;
            case LOG_LEVEL_INFO:  levelStr = "[INFO] "; break;
            case LOG_LEVEL_DEBUG: levelStr = "[DEBUG]"; break;
        }
        
        string logMessage = TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS) + " " + levelStr + " " + message + "\n";
        
        FileWriteString(m_fileHandle, logMessage);
        FileFlush(m_fileHandle);
        
        // 同时输出到控制台（可选）
        if(enableConsoleLog && level <= LOG_LEVEL_WARN) {
            Print(logMessage);
        }
    }
    
    void Error(string message) { Log(LOG_LEVEL_ERROR, message); }
    void Warn(string message)  { Log(LOG_LEVEL_WARN, message); }
    void Info(string message)  { Log(LOG_LEVEL_INFO, message); }
    void Debug(string message) { Log(LOG_LEVEL_DEBUG, message); }
    
    bool IsInitialized() { return m_isInitialized; }
    string GetFileName() { return m_fileName; }
    
private:
    string StringReplace(string str, string search, string replace) {
        string result = str;
        int pos = StringFind(result, search);
        while(pos >= 0) {
            result = StringSubstr(result, 0, pos) + replace + StringSubstr(result, pos + StringLen(search));
            pos = StringFind(result, search);
        }
        return result;
    }
    
    string EnumToString(ENUM_LOG_LEVEL level) {
        switch(level) {
            case LOG_LEVEL_NONE:  return "NONE";
            case LOG_LEVEL_ERROR: return "ERROR";
            case LOG_LEVEL_WARN:  return "WARN";
            case LOG_LEVEL_INFO:  return "INFO";
            case LOG_LEVEL_DEBUG: return "DEBUG";
            default: return "UNKNOWN";
        }
    }
};

//+------------------------------------------------------------------+
//| 全局日志对象                                                      |
//+------------------------------------------------------------------+
CLogger g_logger;

//+------------------------------------------------------------------+
//| 日志输出函数                                                      |
//+------------------------------------------------------------------+
void LogError(string message, bool enableConsoleLog = false) {
    if(g_logger.IsInitialized()) g_logger.Log(LOG_LEVEL_ERROR, message, enableConsoleLog);
}

void LogWarn(string message, bool enableConsoleLog = false) {
    if(g_logger.IsInitialized()) g_logger.Log(LOG_LEVEL_WARN, message, enableConsoleLog);
}

void LogInfo(string message, bool enableConsoleLog = false) {
    if(g_logger.IsInitialized()) g_logger.Log(LOG_LEVEL_INFO, message, enableConsoleLog);
}

void LogDebug(string message, bool enableConsoleLog = false) {
    if(g_logger.IsInitialized()) g_logger.Log(LOG_LEVEL_DEBUG, message, enableConsoleLog);
}

// 全局变量声明（需要在主文件中定义）
// extern ENUM_LOG_LEVEL LogLevel;
// extern bool EnableFileLog;
// extern bool EnableConsoleLog;

//+------------------------------------------------------------------+
//| 日志控制函数                                                      |
//+------------------------------------------------------------------+
void InitializeLogging(ENUM_LOG_LEVEL logLevel = LOG_LEVEL_INFO, bool enableFileLog = true, bool enableConsoleLog = false) {
    // 初始化日志系统
    if(enableFileLog) {
        if(!g_logger.Initialize("", logLevel)) {
            Print("日志系统初始化失败！");
        } else {
            g_logger.Log(LOG_LEVEL_INFO, "=== Martingale EA 日志系统启动 ===", enableConsoleLog);
            g_logger.Log(LOG_LEVEL_INFO, "日志级别: " + EnumToString(logLevel), enableConsoleLog);
            g_logger.Log(LOG_LEVEL_INFO, "文件日志: " + (enableFileLog ? "启用" : "禁用"), enableConsoleLog);
            g_logger.Log(LOG_LEVEL_INFO, "控制台日志: " + (enableConsoleLog ? "启用" : "禁用"), enableConsoleLog);
        }
    }
    
    #ifdef SUPPRESS_SYSTEM_LOGS
    // 在回测模式下完全禁用系统日志
    if(MQLInfoInteger(MQL_TESTER)) {
        // 设置交易对象日志级别
        trade.LogLevel(LOG_LEVEL_NO);
        
        // 尝试禁用更多系统日志
        // 注意：某些系统日志无法通过代码完全禁用，需要在终端设置中调整
        
        // 设置交易参数以减少日志输出
        trade.SetDeviationInPoints(0);  // 设置滑点
        trade.SetTypeFilling(ORDER_FILLING_FOK);  // 设置订单填充类型
        trade.SetMarginMode();  // 设置保证金模式
        
        if(g_logger.IsInitialized()) {
            g_logger.Log(LOG_LEVEL_INFO, "回测模式：系统日志已禁用", enableConsoleLog);
        }
    }
    #endif
    
    // 输出日志控制说明
    if(MQLInfoInteger(MQL_TESTER) && enableConsoleLog) {
        Print(LOG_INFO + "=== 日志控制说明 ===");
        Print(LOG_INFO + "如需完全禁用系统日志，请在MT5终端中设置：");
        Print(LOG_INFO + "工具 → 选项 → 专家顾问 → 日志");
        Print(LOG_INFO + "取消勾选：记录交易操作、记录专家顾问操作");
        Print(LOG_INFO + "只保留：记录错误");
        Print(LOG_INFO + "==================");
    }
}

//+------------------------------------------------------------------+
//| 日志级别枚举转字符串函数                                          |
//+------------------------------------------------------------------+
string EnumToString(ENUM_LOG_LEVEL level) {
    switch(level) {
        case LOG_LEVEL_NONE:  return "NONE";
        case LOG_LEVEL_ERROR: return "ERROR";
        case LOG_LEVEL_WARN:  return "WARN";
        case LOG_LEVEL_INFO:  return "INFO";
        case LOG_LEVEL_DEBUG: return "DEBUG";
        default: return "UNKNOWN";
    }
} 